package ixOrm

import (
	"reflect"
	"sync"
)

// 反射结果缓存
var (
	tableNameCache     = make(map[reflect.Type]string)
	primaryKeyCache    = make(map[reflect.Type][]string)
	dbFieldNameCache   = make(map[reflect.Type]map[string]string) // 字段名映射缓存
	reflectMutex       sync.RWMutex
)

// getTableName 获取表名（带缓存优化）
func getTableName(model interface{}) string {
	// 如果模型实现了TableName方法
	if tableNamer, ok := model.(interface{ TableName() string }); ok {
		return tableNamer.TableName()
	}

	// 获取类型
	modelType := reflect.TypeOf(model)
	if modelType.Kind() == reflect.Ptr {
		modelType = modelType.Elem()
	}

	if modelType.Kind() == reflect.Slice {
		modelType = modelType.Elem()
		if modelType.Kind() == reflect.Ptr {
			modelType = modelType.Elem()
		}
	}

	// 先尝试从缓存获取
	reflectMutex.RLock()
	if tableName, exists := tableNameCache[modelType]; exists {
		reflectMutex.RUnlock()
		return tableName
	}
	reflectMutex.RUnlock()

	// 缓存中没有，计算并缓存结果
	tableName := toSnakeCase(modelType.Name())

	reflectMutex.Lock()
	tableNameCache[modelType] = tableName
	reflectMutex.Unlock()

	return tableName
}

// toSnakeCase 转换为蛇形命名
func toSnakeCase(str string) string {
	var result []rune
	for i, r := range str {
		if i > 0 && isUpper(r) {
			result = append(result, '_')
		}
		result = append(result, toLower(r))
	}
	return string(result)
}

// isUpper 判断是否为大写字母
func isUpper(r rune) bool {
	return r >= 'A' && r <= 'Z'
}

// toLower 转换为小写字母
func toLower(r rune) rune {
	if isUpper(r) {
		return r + 32
	}
	return r
}

// isZero 检查值是否为零值
func isZero(v interface{}) bool {
	if v == nil {
		return true
	}

	value := reflect.ValueOf(v)
	switch value.Kind() {
	case reflect.String:
		return value.String() == ""
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return value.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return value.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return value.Float() == 0
	case reflect.Bool:
		return !value.Bool()
	case reflect.Ptr, reflect.Interface:
		return value.IsNil()
	case reflect.Slice, reflect.Map, reflect.Array:
		return value.Len() == 0
	}

	return false
}

// mergeMaps 合并map
func mergeMaps(maps ...map[string]interface{}) map[string]interface{} {
	result := make(map[string]interface{})
	for _, m := range maps {
		for k, v := range m {
			result[k] = v
		}
	}
	return result
}

// contains 检查切片是否包含元素
func contains(slice []string, item string) bool {
	for _, s := range slice {
		if s == item {
			return true
		}
	}
	return false
}

// unique 去重切片
func unique(slice []string) []string {
	keys := make(map[string]bool)
	var result []string

	for _, item := range slice {
		if !keys[item] {
			keys[item] = true
			result = append(result, item)
		}
	}

	return result
}
